package fun.stgoder.easydarwin.jobs.bl.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fun.stgoder.easydarwin.jobs.bl.BL;
import fun.stgoder.easydarwin.jobs.bl.entity.Job;
import fun.stgoder.easydarwin.jobs.comm.Constants;

public enum MergeFileExecutor {

    INSTANCE;

    private final Logger logger = LoggerFactory.getLogger(MergeFileExecutor.class);

    private ExecutorService executor;

    {
        int processors = Runtime.getRuntime().availableProcessors();
        executor = new ThreadPoolExecutor(processors * 2, // core size
                processors * 2 * 2, 60L, TimeUnit.SECONDS, // maximum size
                new LinkedBlockingQueue<Runnable>(128), // task queue size
                Executors.defaultThreadFactory(), // thread factory
                new RejectedExecutionHandler() { // reject policy
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // abort direct
                        if (Constants.TEST_MODE)
                            logger.info("discard");
                    }
                });
    }

    public class MergeFileTask implements Runnable {

        private final Logger logger = LoggerFactory.getLogger(MergeFileTask.class);

        private Job job;

        public MergeFileTask(Job job) {
            this.job = job;
        }

        @Override
        public void run() {
            try {
                BL.JOB.stopJobAndMergeFile(job);
            } catch (Exception e) {
                if (Constants.TEST_MODE) {
                    logger.error("merge file in executor", e);
                } else {
                    logger.error("merge file in executor: " + e.getMessage());
                }
            }
        }

        public Job job() {
            return job;
        }

    }

    public void execute(Job job) {
        executor.execute(new MergeFileTask(job));
    }
}
